﻿using FastData;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FastCtr
{

    [Serializable]
    struct NewTCPSetting
    {
        public string ip;
        public int port;
    }


    public partial class NewTCP : UserControl
    {

        public static List<NewTCP> NewTCPList = new List<NewTCP>();
        private bool IsAcceptHEX = false;
        Socket socketC;
        NewTCPSetting setting = new NewTCPSetting();
        public IPEndPoint remoteIpep;
        string ContempData = string.Empty;
        Mode mode = Mode.Stopping;
        AutoResetEvent resetevent = new AutoResetEvent(false);
        object sendback_lock = new object();
        public  string DataBag = "";

        object lock_ivsend = new object();
        public event Action<string> OnReceiveMessage;

        public NewTCP()
        {
            InitializeComponent();
        }




        enum Mode
        {
            Listening,
            Stopping
        }

        public NewTCP(string name)
        {
            InitializeComponent();
            Name = name;
            setting.ip = "0.0.0.0";
            setting.port = 0;
            try
            {
                setting = (NewTCPSetting)FastData.SaveStatic.ReadBinF(name);              
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString());
            }
            remoteIpep = new IPEndPoint(IPAddress.Parse(setting.ip), setting.port);
        }

        public bool SendBackMessageInstantIV(int millisecondsTimeOut, ref List<float> ch1, ref List<float> ch2, ref List<float> ch3, ref List<float> ch4)
        {
            socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                socketC.Connect(remoteIpep);
                // ":START;\r\n"
                byte[] bf = new byte[1024];
             //   byte[] datatest = Encoding.UTF8.GetBytes(":START;\r\n");
                byte[] data = Encoding.UTF8.GetBytes(":MEMory: TVREAl? unit1\r\n");
                socketC.SendTimeout = millisecondsTimeOut;
                socketC.ReceiveTimeout = millisecondsTimeOut;
              //  socketC.SendTo(datatest, remoteIpep);
             //   Thread.Sleep(1100);
                EndPoint endPoint1 = remoteIpep;
                ch1 = new List<float>();
                ch2 = new List<float>();
                ch3 = new List<float>();
                ch4 = new List<float>();
                for (int i = 0; i < 6; i++)
                {
                    socketC.SendTo(data, remoteIpep);
                    Thread.Sleep(20);
                    int l_ = socketC.ReceiveFrom(bf, bf.Length, SocketFlags.None, ref endPoint1);
                    if (l_ == 0)
                    {
                        throw new Exception("");
                    }
                    bf = bf.Skip(0).Take(l_).ToArray();
                    string rt = Encoding.UTF8.GetString(bf);
                    float[] IV_Cell_1_f = Array.ConvertAll(rt.Split(','), delegate (string s) { return float.Parse(s); });
                    ch1.Add(IV_Cell_1_f[0]);
                    ch2.Add(IV_Cell_1_f[1]);
                    ch3.Add(IV_Cell_1_f[2]);
                    ch4.Add(IV_Cell_1_f[3]);
                    Thread.Sleep(180);
                }
                socketC.Disconnect(false);
                socketC.Close();
                socketC.Dispose();
                return true;
            }
            catch
            {
                try
                {
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                    return false;
                }
                catch { return false; }
            }
        }



        public string SendBackMessageInstant(string sendContent, int millisecondsTimeOut)
        {
            socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                socketC.Connect(remoteIpep);
                byte[] bf = new byte[1024];
                byte[] data = Encoding.UTF8.GetBytes(sendContent);
                socketC.SendTimeout = millisecondsTimeOut;
                socketC.ReceiveTimeout = millisecondsTimeOut;
                socketC.SendTo(data, remoteIpep);
                EndPoint endPoint = remoteIpep;
                int l = socketC.ReceiveFrom(bf, bf.Length, SocketFlags.None, ref endPoint);
                if (l == 0)
                {
                    throw new Exception("");
                }
                bf = bf.Skip(0).Take(l).ToArray();
                string content = Encoding.UTF8.GetString(bf);
                ContempData = content;
                socketC.Disconnect(false);
                socketC.Close();
                socketC.Dispose();
                return content;
            }
            catch
            {
                try
                {
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                    return null;
                }
                catch { return null; }
            }
        }


        public string SendBackMessageInstant(string sendContent, int millisecondsTimeOut,out long time)
        {
            long a = Environment.TickCount;
            socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            try
            {
                long b = Environment.TickCount;
                socketC.Connect(remoteIpep);
                Thread.Sleep(150);
                long time1 = Environment.TickCount - b;
               // SaveStatic.SaveTxt("e:\\time1.txt", time1.ToString(), true);
                byte[] bf = new byte[1024];
                byte[] data = Encoding.UTF8.GetBytes(sendContent);
                socketC.SendTimeout = millisecondsTimeOut;
                socketC.ReceiveTimeout = millisecondsTimeOut;
                socketC.SendTo(data, remoteIpep);
                EndPoint endPoint = remoteIpep;
                int l = socketC.ReceiveFrom(bf, bf.Length, SocketFlags.None, ref endPoint);
                if (l == 0)
                {
                    throw new Exception("");
                }
                bf = bf.Skip(0).Take(l).ToArray();
                string content = Encoding.UTF8.GetString(bf);
                ContempData = content;
                socketC.Disconnect(false);
                socketC.Close();
                socketC.Dispose();
                time = Environment.TickCount - a;
                return content;
            }
            catch
            {
                try
                {
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                    time = Environment.TickCount - a;
                    return null;
                }
                catch {
                    time = Environment.TickCount - a;
                    return null; }
            }
        }

        public static string SendBackMessageInstantLong(NewTCP newTCP, string sendContent,bool isHEX, int millisecondsTimeOut)
        {
            try
            {
                byte[] bf = new byte[1024];
                byte[] data;
                if (isHEX)
                {
                    byte[] sendbyte = ConvertHexStrToByteArray(sendContent);
                    data = sendbyte;
                }
                else
                {
                    data = Encoding.UTF8.GetBytes(sendContent);

                }
                newTCP.socketC.SendTimeout = millisecondsTimeOut;
                newTCP.socketC.ReceiveTimeout = millisecondsTimeOut;
                newTCP.socketC.SendTo(data, newTCP.remoteIpep);



                EndPoint endPoint = newTCP.remoteIpep;
                int l = newTCP.socketC.ReceiveFrom(bf, bf.Length, SocketFlags.None, ref endPoint);
                if (l == 0)
                {
                    throw new Exception("");
                }
                bf = bf.Skip(0).Take(l).ToArray();

                if (isHEX)
                {
                    List<string> str = new List<string>();
                    foreach (byte bt in bf)
                    {
                        str.Add(Convert.ToInt64(bt).ToString("X2"));
                    }
                    return string.Join(" ", str);
                }
                else
                {
                   return Encoding.UTF8.GetString(bf);
                }
            }
            catch
            {
                return null;
            }

        }


        public static void SendBackMessageLong(NewTCP newTCP, string sendContent, bool _IsSendHEX, int millisecondsTimeOut)
        {
            try
            {
                byte[] data;
                if (_IsSendHEX)
                {
                    byte[] sendbyte = ConvertHexStrToByteArray(sendContent);
                    data = sendbyte;
                }
                else
                {
                    data = Encoding.UTF8.GetBytes(sendContent);
                }
                newTCP.socketC.SendTimeout = millisecondsTimeOut;
                newTCP.socketC.SendTo(data, newTCP.remoteIpep);
            }
            catch (Exception)
            {
                throw new Exception("TCP发送失败！");
            }
        }


        /// <summary>
        /// 连接
        /// </summary>
        /// 


        AutoResetEvent autoReset = new AutoResetEvent(true);
        public bool Connect()
        {
            try
            {
                socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketC.Connect(remoteIpep);
                if (socketC.Connected)
                {
                 
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }
      

        /// <summary>
        /// 断开连接
        /// </summary>
        public void DisConnect()
        {
            try
            { 
                socketC.Disconnect(false);
                socketC.Close();
            }
            catch
            { }
        }

        /// <summary>
        /// 反馈当前TCP的连接状态
        /// </summary>
        /// <returns></returns>
        public bool ConnectionStatus()
        {
            return socketC.Connected;
        }

        /// <summary>
        /// TCP 重连
        /// </summary>
        public void Reconnection()
        {
            if (!socketC.Connected)
            {
                Connect();
            }
        }



        /// <summary>
        /// 发送一次信息  
        /// </summary>
        /// <param name="sendContent"></param>
        public void SendMessage(string sendContent, bool _IsSendHEX)
        {
            try
            {
                if (socketC == null)
                {
                    socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    socketC.Connect(remoteIpep);
                }
                if (socketC.Connected == false)
                {
                    socketC.Close();
                    socketC.Dispose();
                    socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    socketC.Connect(remoteIpep);
                }
                byte[] data;
                if (_IsSendHEX)
                {
                    byte[] sendbyte = ConvertHexStrToByteArray(sendContent);
                    data = sendbyte;
                }
                else
                {
                    data = Encoding.UTF8.GetBytes(sendContent);
                }
                socketC.Send(data);
              
            }
            catch (Exception exp)
            {
                try
                {
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                }
                catch { }
            }
        }



        public void SendMessage(string sendContent)
        {
            lock (sendback_lock)
            {
                try
                {
                    socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    socketC.Connect(remoteIpep);
                    byte[] data = Encoding.UTF8.GetBytes(sendContent);
                    socketC.Send(data);
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                }
                catch (Exception E)
                {
                    throw new Exception("TCP发送失败！");
                }
            }
        }

        /// <summary>
        /// 接受一次信息
        /// </summary>
        /// <returns></returns>
        public string ReceiveMessage()
        {
            try
            {
                if (Thread.CurrentThread.Name == null)
                {
                    Thread.CurrentThread.Name = "监测线程";
                }
                byte[] bf = new byte[1024];
                EndPoint endPoint = remoteIpep;
                // int l = socketC.ReceiveFrom(bf, bf.Length, SocketFlags.None, ref endPoint);
                int l = socketC.Receive(bf);
                bf = bf.Skip(0).Take(l).ToArray();
                string message = null;
                if (!IsAcceptHEX)
                {
                    message = Encoding.UTF8.GetString(bf);
                }
                else
                {
                    message = ConvertByteArrayToHexStr(bf);
                }
                ContempData = message;
                return message;
            }
            catch (Exception exp)
            {
                Thread.Sleep(500);
                throw new Exception(exp.ToString());
            }
        }



        public string SendBackMessageInstant(string sendContent, bool _IsSendHEX, int millisecondsTimeOut)
        {
            try
            {
                socketC = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketC.Connect(remoteIpep);
                byte[] bf = new byte[1024];
                byte[] data;
                if (_IsSendHEX)
                {
                    byte[] sendbyte = ConvertHexStrToByteArray(sendContent);
                    data = sendbyte;
                }
                else
                {
                    data = Encoding.UTF8.GetBytes(sendContent);

                }
                socketC.SendTimeout = millisecondsTimeOut;
                socketC.ReceiveTimeout = millisecondsTimeOut;
                socketC.SendTo(data, remoteIpep);
                EndPoint endPoint = remoteIpep;
                int l = socketC.ReceiveFrom(bf, bf.Length, SocketFlags.None, ref endPoint);
                if (l == 0)
                {
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                    throw new Exception("");
                }
                bf = bf.Skip(0).Take(l).ToArray();


                if (_IsSendHEX)
                {
                    ContempData = ConvertByteArrayToHexStr(bf);
                }
                else
                {
                    ContempData = Encoding.UTF8.GetString(bf);
                }

                socketC.Disconnect(false);
                socketC.Close();
                socketC.Dispose();
                return ContempData;
            }
            catch
            {
                try
                {
                    socketC.Disconnect(false);
                    socketC.Close();
                    socketC.Dispose();
                    return null;
                }
                catch { return null; }
            }
        }


        private static byte[] ConvertHexStrToByteArray(string hexStr)
        {
            string[] array = new string[hexStr.Length / 2];
            byte[] bytes = new byte[array.Length];
            for (int i = 0; i < hexStr.Length; i++)
            {
                array[i / 2] += hexStr[i];
            }
            for (int i = 0; i < array.Length; i++)
            {
                bytes[i] = Convert.ToByte(array[i], 16);
            }
            return bytes;
        }


        private string ConvertByteArrayToHexStr(byte[] btarry)
        {
            List<string> str = new List<string>();
            foreach (byte bt in btarry)
            {
                str.Add(Convert.ToInt64(bt).ToString("X2"));
            }
            return string.Join(" ", str);
        }


        /// <summary>
        /// 持续接收返回值
        /// open后就需要打开
        /// </summary>
        public void StopTcpMessage()
        {
            socketC.Disconnect(false);
            socketC.Close();
            socketC.Dispose();
        }

        //public void StartReceivingMessage()
        //{
        //    Task task = new Task(() =>
        //    {
        //        mode = Mode.Listening;
        //        // byte[] data = Encoding.UTF8.GetBytes(socketC.LocalEndPoint.ToString() + ": StartReceiving");
        //        // socketC.Send(data);
        //        while (mode == Mode.Listening)
        //        {
        //            GC.Collect();
        //            string message = ReceiveMessage();
        //            ContempData = message;
        //            resetevent.Set();
        //        }
        //    }, TaskCreationOptions.LongRunning);
        //    task.Start();
        //}

        public void StartReceivingMessage()
        {
            Task task = new Task(() =>
            {

                mode = Mode.Listening;
                // byte[] data = Encoding.UTF8.GetBytes(socketC.LocalEndPoint.ToString() + ": StartReceiving");
                // socketC.Send(data);
                while (mode == Mode.Listening)
                {
                    try
                    {
                        GC.Collect();
                        string message = ReceiveMessage();
                        ContempData = message;
                        resetevent.Set();
                        OnReceiveMessage?.Invoke(ContempData);
                    }
                    catch(Exception exp)
                    {

                    }
                }
            }, TaskCreationOptions.LongRunning);
            task.Start();
        }


        /// <summary>
        /// 关闭持续接收信息的线程
        /// </summary>
        public void StopReceivingMessage()
        {
            mode = Mode.Stopping;
            System.Threading.Thread.Sleep(10);
            //byte[] data = Encoding.UTF8.GetBytes("StopReceiving");
            //socketC.Send(data);
        }

        public void KeepAlive(string _databag)
        {
            //Task task = new Task(() =>
            //  {
            //      while (true)
            //      {
            //          Thread.Sleep(5000);
            //          string aa = SendBackMessageInstant(dataBag, 2000);
            //          if (aa == null)
            //          {
            //              Connect(2000);
            //              FastData.Folder_Helper.CreateFolder("NewTcpLog");
            //              FastData.SaveStatic.SaveTxt($"NewTcpLog\\{DateTime.Now.ToString("yyyy-MM-dd")}.txt", $"本地端口{socketC.LocalEndPoint.ToString()},远程端口{socketC.RemoteEndPoint.ToString()}重连一次！", true);
            //          }
            //      }
            //  }, TaskCreationOptions.LongRunning);
            //task.Start();
            //DataBag = _databag;
            //NewTCPList.Add(this);


        }



        /// <summary>
        /// 获取本地 IP
        /// </summary>
        /// <returns></returns>
        public static string[] GetLocalIp()
        {
            List<string> IPList = new List<string>();
            ///获取本地的IP地址
            string AddressIP = string.Empty;
            foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    AddressIP = _IPAddress.ToString();
                    IPList.Add(AddressIP);
                }
            }
            return IPList.ToArray();
        }

        private void NewTCP_Load(object sender, EventArgs e)
        {
            textBox2.Text = setting.ip;
            textBox4.Text = setting.port.ToString();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                setting.ip = textBox2.Text;
                setting.port = int.Parse(textBox4.Text);
                remoteIpep = new IPEndPoint(IPAddress.Parse(setting.ip), setting.port);
            }
            catch
            {
                MessageBox.Show("输入信息有误！");
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            FastData.SaveStatic.SaveBinF(Name, setting);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (button5.Text == "打开端口")
            {
                Connect();
                button5.Text = "关闭端口";
            }
            else
            {
                DisConnect();
                button5.Text = "打开端口";
            }

        }

        private void button6_Click(object sender, EventArgs e)
        {
            DisConnect();
        }

        private void button8_Click(object sender, EventArgs e)
        {
            if (button8.Text == "开始监听")
            {
                StopTcpMessage();
                button8.Text = "停止监听";
            }
            else
            {
                StopReceivingMessage();
                button8.Text = "开始监听";
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            StopReceivingMessage();
        }

        private void NewTCP_ParentChanged(object sender, EventArgs e)
        {
            if (this.ParentForm != null)
            {
                ParentForm.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing);
                ParentForm.AutoSize = true;
                ParentForm.StartPosition = FormStartPosition.CenterScreen;
                ParentForm.Text = Name;
                timer1.Start();
            }
            else
            {
                timer1.Stop();
            }
        }

        private void ParentForm_FormClosing(object sender, FormClosingEventArgs e)
        {
           ((Form)sender).Controls.Clear();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                textBox1.Text = ContempData;
                if (mode == Mode.Listening)
                {
                    button1.Text = "停止监听";
                    label6.BackColor = Color.LimeGreen;
                }
                else
                {
                    button1.Text = "开始监听";
                    label6.BackColor = Color.Red;
                }

                if (mode == Mode.Stopping)
                {
                    textBox2.Enabled = true;
                    textBox4.Enabled = true;
                    button3.Enabled = true;
                }
                else
                {
                    textBox2.Enabled = true;
                    textBox4.Enabled = true;
                    button3.Enabled = true;
                }

                if (ConnectionStatus())
                {
                    label5.Text = "最近一次已连接";
                    label5.BackColor = Color.LimeGreen;
                    button8.Enabled = true;
                }
                else
                {
                    label5.Text = "最后一次连接失败";
                    label5.BackColor = Color.Red;
                    button8.Enabled = true;
                    button5.Enabled = true;
                }


                if (mode == Mode.Listening)
                {
                    button8.Text = "停止监听";
                    label6.Text = "监听中";
                    label6.BackColor = Color.LimeGreen;
                    button5.Enabled = true;
                }
                else
                {
                    button8.Text = "开始监听";
                    label6.Text = "不监听";
                    label6.BackColor = Color.Red;
                    button5.Enabled = true;
                }

                if (ConnectionStatus())
                {
                    button5.Text = "关闭端口";
                }
                else
                {
                    button5.Text = "打开端口";
                }
            }
            catch { }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                SendMessage(textBox3.Text,false);
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.ToString());
            }
        }

        private void button9_Click(object sender, EventArgs e)
        {

        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            IsAcceptHEX = checkBox1.Checked;
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void button6_Click_1(object sender, EventArgs e)
        {
            socketC.Close();
        }
    }
}
